package cn.tedu.util;

import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @author 青石
 */
public class RedisUtil {

    /**
     * 向 redis 中插入 或 修改一条数据
     * @param template 模板 必须
     * */
    public static void setItem(RedisTemplate<String, Serializable> template,String key, Serializable value){
        templateExamine(template);
        template.opsForValue().set(key,value);
    }

    /**
     * 向 redis 中插入或设置一条带有效时间的数据
     * @param template 模板 必须
     * @param count 时间值
     * @param unit 时间单位
     * */
    public static void setItem(RedisTemplate<String, Serializable> template, String key, Serializable value, long count, TimeUnit unit){
        templateExamine(template);
        template.opsForValue().set(key,value,count,unit);
    }

    /**
     * 向 redis 中 插入或设置一条列表
     * @param direction 插入列表位置 0 左 1 右
     * */
    public static void setList(RedisTemplate<String, Serializable> template, String key, List<Serializable> list, int direction){
        templateExamine(template);
        ListOperations<String, Serializable> opsForList = template.opsForList();
        if (direction == 0){
            for (Serializable serializable : list) {
                opsForList.leftPush(key,serializable);
            }
        }else if(direction == 1){
            for (Serializable serializable : list) {
                opsForList.rightPush(key,serializable);
            }
        }
    }

    /**
     * 删除多个key
     * */
    public static void removeX(RedisTemplate<String, Serializable> template, String... keys){
        List<String> list = new ArrayList<>();
        Collections.addAll(list, keys);
        template.delete(list);
    }

    /**
     * 获取列表中数据
     * */
    public static<T> List<T> getList(RedisTemplate<String, Serializable> template, String key, int start, int end, Class<T> tClass){
        templateExamine(template);
        List<T> result = new ArrayList<>();
        List<Serializable> list = template.opsForList().range(key, start, end);
        if (list == null){
            return null;
        }
        for (Serializable item : list) {
            result.add(tClass.cast(item));
        }
        return result;
    }

    /**
     * 在redis中查询一条数据
     * @param tClass 指定返回值的类型
     * */
    public static <T> T getItem(RedisTemplate<String,Serializable> template, String key, Class<T> tClass){
        templateExamine(template);
        return tClass.cast(template.opsForValue().get(key));
    }

    public static <T> List<T> getListByLikeKeys(StringRedisTemplate template, String pattern, Class<T> tClass){
        templateExamine(template);
        Set<String> keys = template.keys(pattern);
        if (keys == null || keys.size() == 0){
            return null;
        }
        List<String> list = template.opsForValue().multiGet(keys);
        if (list == null || list.size() == 0){
            return null;
        }
        return JsonUtil.jsonListConvertObjList(list,tClass);
    }

    private static void templateExamine(RedisTemplate<String, Serializable> template){
        if (template == null){
            throw new RuntimeException("麻烦传入redis 模板");
        }
    }

    private static void templateExamine(StringRedisTemplate template){
        if (template == null){
            throw new RuntimeException("麻烦传入redis 模板");
        }
    }

}
